// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package os

import (
	"syscall"
)

// MkdirAll创建名为path的目录，
// 以及任何必要的父目录，并返回nil、
// 否则返回错误。
// 权限位perm（在umask之前）用于MkdirAll创建的所有
// 目录。
// 如果path已经是一个目录，则MkdirAll不执行任何操作
// 并返回nil。
func MkdirAll(path string, perm FileMode) error {
	// 快速路径：如果我们可以判断路径是目录还是文件，那么请停止使用成功或错误。
	dir, err := Stat(path)
	if err == nil {
		if dir.IsDir() {
			return nil
		}
		return &PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR}
	}

	// 慢路径：确保父级存在，然后调用Mkdir获取路径。
	i := len(path)
	for i > 0 && IsPathSeparator(path[i-1]) { // 跳过尾随路径分隔符。
		i--
	}

	j := i
	for j > 0 && !IsPathSeparator(path[j-1]) { // 向后扫描元素。
		j--
	}

	if j > 1 {
		// 创建父级。
		err = MkdirAll(fixRootDirectory(path[:j-1]), perm)
		if err != nil {
			return err
		}
	}

	// 父项现在存在；调用Mkdir并使用其结果。
	err = Mkdir(path, perm)
	if err != nil {
		// 处理像“foo/”这样的参数通过
		// 再次检查目录是否不存在。
		dir, err1 := Lstat(path)
		if err1 == nil && dir.IsDir() {
			return nil
		}
		return err
	}
	return nil
}

// RemoveAll删除路径及其包含的所有子级。
// 它删除了它能删除的所有内容，但返回了它遇到的第一个错误
// 。如果路径不存在，RemoveAll 
// 返回nil（无错误）。
// 如果有错误，则类型为*PathError。
func RemoveAll(path string) error {
	return removeAll(path)
}

// endsWithDot报告路径的最终组件是否为“”。
func endsWithDot(path string) bool {
	if path == "." {
		return true
	}
	if len(path) >= 2 && path[len(path)-1] == '.' && IsPathSeparator(path[len(path)-2]) {
		return true
	}
	return false
}
